🌎 rns.kin.earth git 🌍
Commit bab779a34cc9b1895f3b1df1ae0e2f8ef3cfb2c1
Parents : 97f97eb
Author : Mark Qvist <mark@unsigned.io>
Date : 2023-06-13T16:10:47+02:00
Fixed race condition for link initiators on timed out link establishment
Changes
3 files changed, 52 insertions(+), 41 deletions(-)
Diff
diff --git a/RNS/Link.py b/RNS/Link.py
index 162f820e..0b7b856c 100644
--- a/RNS/Link.py
+++ b/RNS/Link.py
@@ -264,41 +264,50 @@ class Link:
self.had_outbound()
def validate_proof(self, packet):
- if self.status == Link.PENDING:
- if self.initiator and len(packet.data) == RNS.Identity.SIGLENGTH//8+Link.ECPUBSIZE//2:
- peer_pub_bytes = packet.data[RNS.Identity.SIGLENGTH//8:RNS.Identity.SIGLENGTH//8+Link.ECPUBSIZE//2]
- peer_sig_pub_bytes = self.destination.identity.get_public_key()[Link.ECPUBSIZE//2:Link.ECPUBSIZE]
- self.load_peer(peer_pub_bytes, peer_sig_pub_bytes)
- self.handshake()
-
- self.establishment_cost += len(packet.raw)
- signed_data = self.link_id+self.peer_pub_bytes+self.peer_sig_pub_bytes
- signature = packet.data[:RNS.Identity.SIGLENGTH//8]
-
- if self.destination.identity.validate(signature, signed_data):
- self.rtt = time.time() - self.request_time
- self.attached_interface = packet.receiving_interface
- self.__remote_identity = self.destination.identity
- self.status = Link.ACTIVE
- self.activated_at = time.time()
- self.last_proof = self.activated_at
- RNS.Transport.activate_link(self)
- RNS.log("Link "+str(self)+" established with "+str(self.destination)+", RTT is "+str(round(self.rtt, 3))+"s", RNS.LOG_VERBOSE)
+ try:
+ if self.status == Link.PENDING:
+ if self.initiator and len(packet.data) == RNS.Identity.SIGLENGTH//8+Link.ECPUBSIZE//2:
+ peer_pub_bytes = packet.data[RNS.Identity.SIGLENGTH//8:RNS.Identity.SIGLENGTH//8+Link.ECPUBSIZE//2]
+ peer_sig_pub_bytes = self.destination.identity.get_public_key()[Link.ECPUBSIZE//2:Link.ECPUBSIZE]
+ self.load_peer(peer_pub_bytes, peer_sig_pub_bytes)
+ self.handshake()
+
+ self.establishment_cost += len(packet.raw)
+ signed_data = self.link_id+self.peer_pub_bytes+self.peer_sig_pub_bytes
+ signature = packet.data[:RNS.Identity.SIGLENGTH//8]
- if self.rtt != None and self.establishment_cost != None and self.rtt > 0 and self.establishment_cost > 0:
- self.establishment_rate = self.establishment_cost/self.rtt
-
- rtt_data = umsgpack.packb(self.rtt)
- rtt_packet = RNS.Packet(self, rtt_data, context=RNS.Packet.LRRTT)
- rtt_packet.send()
- self.had_outbound()
-
- if self.callbacks.link_established != None:
- thread = threading.Thread(target=self.callbacks.link_established, args=(self,))
- thread.daemon = True
- thread.start()
- else:
- RNS.log("Invalid link proof signature received by "+str(self)+". Ignoring.", RNS.LOG_DEBUG)
+ if self.destination.identity.validate(signature, signed_data):
+ if self.status != Link.PENDING:
+ raise IOError("Invalid link state for proof validation")
+
+ self.rtt = time.time() - self.request_time
+ self.attached_interface = packet.receiving_interface
+ self.__remote_identity = self.destination.identity
+ self.status = Link.ACTIVE
+ self.activated_at = time.time()
+ self.last_proof = self.activated_at
+ RNS.Transport.activate_link(self)
+ RNS.log("Link "+str(self)+" established with "+str(self.destination)+", RTT is "+str(round(self.rtt, 3))+"s", RNS.LOG_VERBOSE)
+
+ if self.rtt != None and self.establishment_cost != None and self.rtt > 0 and self.establishment_cost > 0:
+ self.establishment_rate = self.establishment_cost/self.rtt
+
+ rtt_data = umsgpack.packb(self.rtt)
+ rtt_packet = RNS.Packet(self, rtt_data, context=RNS.Packet.LRRTT)
+ rtt_packet.send()
+ self.had_outbound()
+
+ if self.callbacks.link_established != None:
+ thread = threading.Thread(target=self.callbacks.link_established, args=(self,))
+ thread.daemon = True
+ thread.start()
+ else:
+ RNS.log("Invalid link proof signature received by "+str(self)+". Ignoring.", RNS.LOG_DEBUG)
+
+ except Exception as e:
+ self.status = Link.CLOSED
+ RNS.log("An error ocurred while validating link request proof on "+str(self)+".", RNS.LOG_ERROR)
+ RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
def identify(self, identity):
@@ -520,16 +529,16 @@ class Link:
next_check = self.request_time + self.establishment_timeout
sleep_time = next_check - time.time()
if time.time() >= self.request_time + self.establishment_timeout:
- if self.initiator:
- RNS.log("Timeout waiting for link request proof", RNS.LOG_DEBUG)
- else:
- RNS.log("Timeout waiting for RTT packet from link initiator", RNS.LOG_DEBUG)
-
self.status = Link.CLOSED
self.teardown_reason = Link.TIMEOUT
self.link_closed()
sleep_time = 0.001
+ if self.initiator:
+ RNS.log("Timeout waiting for link request proof", RNS.LOG_DEBUG)
+ else:
+ RNS.log("Timeout waiting for RTT packet from link initiator", RNS.LOG_DEBUG)
+
elif self.status == Link.ACTIVE:
activated_at = self.activated_at if self.activated_at != None else 0
last_inbound = max(max(self.last_inbound, self.last_proof), activated_at)
@@ -847,7 +856,7 @@ class Link:
try:
self.fernet = Fernet(self.derived_key)
except Exception as e:
- RNS.log("Could not "+str(self)+" instantiate Fernet while performin encryption on link. The contained exception was: "+str(e), RNS.LOG_ERROR)
+ RNS.log("Could not instantiate Fernet while performin encryption on link "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
raise e
return self.fernet.encrypt(plaintext)
diff --git a/RNS/Transport.py b/RNS/Transport.py
index 67331801..e9c8d8af 100755
--- a/RNS/Transport.py
+++ b/RNS/Transport.py
@@ -1741,6 +1741,8 @@ class Transport:
def activate_link(link):
RNS.log("Activating link "+str(link), RNS.LOG_EXTREME)
if link in Transport.pending_links:
+ if link.status != Link.PENDING:
+ raise IOError("Invalid link state for link activation")
Transport.pending_links.remove(link)
Transport.active_links.append(link)
link.status = RNS.Link.ACTIVE
diff --git a/RNS/_version.py b/RNS/_version.py
index 6b27eeeb..86716a71 100644
--- a/RNS/_version.py
+++ b/RNS/_version.py
@@ -1 +1 @@
-__version__ = "0.5.4"
+__version__ = "0.5.5"
Served by rngit 1.5.2 - Generated in 0.07s